#include <gtest/gtest.h>
#include <thread>
#include <vector>
#include <atomic>
#include <chrono>
#include "Thread/Semaphore.h"

using namespace toolkit;
using namespace std;

class SemaphoreTest : public ::testing::Test {
protected:
    void SetUp() override {
    }

    void TearDown() override {
    }
};

// 测试基本的 post 和 wait 功能
TEST_F(SemaphoreTest, BasicFunctionality) {
    Semaphore sem(0);
    bool flag = false;

    thread worker([&]() {
        sem.wait();
        flag = true;
    });

    // 确保线程已启动但被信号量阻塞
    this_thread::sleep_for(chrono::milliseconds(100));
    EXPECT_FALSE(flag);

    // 发送信号
    sem.post();
    
    // 等待线程完成
    worker.join();
    EXPECT_TRUE(flag);
}

// 测试初始值构造函数
TEST_F(SemaphoreTest, InitialValue) {
    const int INITIAL_COUNT = 3;
    Semaphore sem(INITIAL_COUNT);
    
    // 验证初始值
    EXPECT_EQ(sem.getValue(), INITIAL_COUNT);
    
    atomic<int> counter(0);
    auto worker = [&]() {
        sem.wait();
        counter++;
    };

    // 创建多个线程，它们应该能够立即获取信号量
    vector<thread> threads;
    for (int i = 0; i < INITIAL_COUNT; ++i) {
        threads.emplace_back(worker);
    }

    // 等待所有线程完成
    for (auto& t : threads) {
        t.join();
    }

    EXPECT_EQ(counter, INITIAL_COUNT);
    EXPECT_EQ(sem.getValue(), 0);
}

// 测试 tryWait 功能
TEST_F(SemaphoreTest, NonBlockingWait) {
    Semaphore sem(1);
    
    // 第一次应该成功
    EXPECT_TRUE(sem.tryWait());
    EXPECT_EQ(sem.getValue(), 0);
    
    // 第二次应该失败
    EXPECT_FALSE(sem.tryWait());
    EXPECT_EQ(sem.getValue(), 0);
    
    // 增加信号量后再次尝试
    sem.post();
    EXPECT_TRUE(sem.tryWait());
}

// 测试带超时的等待
TEST_F(SemaphoreTest, TimeoutWait) {
    Semaphore sem(0);
    
    // 测试超时情况
    auto start = chrono::steady_clock::now();
    bool result = sem.waitFor(chrono::milliseconds(100));
    auto end = chrono::steady_clock::now();
    
    EXPECT_FALSE(result);
    EXPECT_GE(chrono::duration_cast<chrono::milliseconds>(end - start).count(), 90);
    
    // 测试不超时情况
    sem.post();
    result = sem.waitFor(chrono::milliseconds(100));
    EXPECT_TRUE(result);
    EXPECT_EQ(sem.getValue(), 0);
}

// 测试多次 post 和 wait
TEST_F(SemaphoreTest, MultipleSignals) {
    Semaphore sem(0);
    atomic<int> counter(0);
    const int NUM_SIGNALS = 5;

    thread worker([&]() {
        for (int i = 0; i < NUM_SIGNALS; ++i) {
            sem.wait();
            counter++;
        }
    });

    // 发送多个信号
    for (int i = 0; i < NUM_SIGNALS; ++i) {
        sem.post();
        this_thread::sleep_for(chrono::milliseconds(10));
    }

    worker.join();
    EXPECT_EQ(counter, NUM_SIGNALS);
}

// 测试多个线程等待单个信号
TEST_F(SemaphoreTest, MultipleWaiters) {
    Semaphore sem(0);
    atomic<int> woken(0);
    const int NUM_WAITERS = 5;

    vector<thread> waiters;
    for (int i = 0; i < NUM_WAITERS; ++i) {
        waiters.emplace_back([&]() {
            sem.wait();
            woken++;
        });
    }

    // 确保所有线程都在等待
    this_thread::sleep_for(chrono::milliseconds(100));
    EXPECT_EQ(woken, 0);

    // 一次性发送多个信号
    sem.post(NUM_WAITERS);

    // 等待所有线程完成
    for (auto& t : waiters) {
        t.join();
    }

    EXPECT_EQ(woken, NUM_WAITERS);
}

// 测试在高并发情况下的正确性
TEST_F(SemaphoreTest, ConcurrencyStressTest) {
    Semaphore sem(0);
    atomic<int> sum(0);
    const int NUM_PRODUCERS = 5;
    const int NUM_CONSUMERS = 5;
    const int ITEMS_PER_PRODUCER = 100;
    atomic<bool> done(false);

    // 消费者线程
    vector<thread> consumers;
    for (int i = 0; i < NUM_CONSUMERS; ++i) {
        consumers.emplace_back([&]() {
            while (true) {
                if (done && sem.getValue() == 0) break;
                
                if (sem.waitFor(chrono::milliseconds(10))) {
                    sum++;
                }
            }
        });
    }

    // 生产者线程
    vector<thread> producers;
    for (int i = 0; i < NUM_PRODUCERS; ++i) {
        producers.emplace_back([&]() {
            for (int j = 0; j < ITEMS_PER_PRODUCER; ++j) {
                sem.post();
                this_thread::sleep_for(chrono::microseconds(10));
            }
        });
    }

    // 等待所有生产者完成
    for (auto& t : producers) {
        t.join();
    }

    // 等待所有项目被消费
    this_thread::sleep_for(chrono::seconds(1));
    done = true;

    // 等待所有消费者完成
    for (auto& t : consumers) {
        t.join();
    }

    EXPECT_EQ(sum, NUM_PRODUCERS * ITEMS_PER_PRODUCER);
}

// 测试 getValue 方法
TEST_F(SemaphoreTest, GetValueMethod) {
    Semaphore sem(5);
    EXPECT_EQ(sem.getValue(), 5);
    
    sem.wait();
    EXPECT_EQ(sem.getValue(), 4);
    
    sem.post(3);
    EXPECT_EQ(sem.getValue(), 7);
}

int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}